package com.xc.ksxt.controller;

import cn.hutool.http.HttpUtil;
import com.xc.common.object.Constant;
import com.xc.common.tool.Helper;
import com.xc.common.tool.WordUtil;
import com.xc.common.tool.WordUtils;
import com.xc.db.tables.Choice;
import com.xc.db.tables.LibQuestion;
import com.xc.db.tables.Question;
import com.xc.ksxt.entity.*;
import com.xc.ksxt.service.*;
import com.xc.ksxt.vo.PaperVO;
import com.xc.sys.entity.SysDictEntity;
import com.xc.sys.service.SysDictService;
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.TranscodingHints;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.dom4j.*;
import org.dom4j.Document;
import org.joda.time.DateTime;
import org.jooq.*;
import org.jsoup.Jsoup;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
import sun.misc.BASE64Decoder;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.List;
import javax.imageio.ImageIO;
import javax.net.ssl.*;
import javax.security.cert.CertificateException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static org.jooq.impl.DSL.*;

@Controller
@RequestMapping({ "/wordPaper"})
public class WordPaper {
    @Autowired
    private DSLContext dsl;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private PaperService paperService;
    @Autowired
    private QuestionService questionService;
    @Autowired
    private ChoiceService choiceService;
    private Question QUESTION = Question.QUESTION.as("QUESTION");
    private Choice CHOICE = Choice.CHOICE.as("CHOICE");
    private LibQuestion LIBQUESTIONTB = LibQuestion.LIB_QUESTION.as("LIBQUESTIONTB");
    private String msg = "";
    public static XWPFRun setTitle(XWPFDocument document,String text,int fontSize,String family,boolean bold,ParagraphAlignment alignment){
        XWPFParagraph paragraph = document.createParagraph();
        paragraph.setSpacingBetween(1.5,LineSpacingRule.AUTO);
        paragraph.setSpacingAfterLines(0);
        paragraph.setAlignment(alignment);
        paragraph.setVerticalAlignment(TextAlignment.TOP);
        XWPFRun xwpfRun = paragraph.createRun();
        xwpfRun.setBold(bold);
        xwpfRun.setFontSize(fontSize);
        xwpfRun.setFontFamily(family);
        xwpfRun.setFontFamily("Times New Roman");
        xwpfRun.setText(text);
        return xwpfRun;
    }
    public static XWPFRun setTitle2(XWPFParagraph paragraph,String text,int fontSize,String family,boolean bold,boolean letter){
        XWPFRun xwpfRun = paragraph.createRun();
        xwpfRun.setBold(bold);
        xwpfRun.setFontSize(fontSize);
        xwpfRun.setFontFamily(family);

        if(letter){
            xwpfRun.setFontFamily("Times New Roman");
        }
        xwpfRun.setText(text);
        return xwpfRun;
    }
    public static XWPFRun setTitle3(XWPFRun xwpfRun,String text,int fontSize,String family,boolean bold,boolean letter){

        xwpfRun.setBold(bold);
        xwpfRun.setFontSize(fontSize);
        xwpfRun.setFontFamily(family);
        if(letter)
            xwpfRun.setFontFamily("Times New Roman");
        xwpfRun.setText(text);
        return xwpfRun;
    }
    @GetMapping("export")
    @ResponseBody
    public JSONObject PoiWord(HttpServletResponse response){
        String hasAnswer = request.getParameter("hasAnswer");
        Long paperId = Long.valueOf(request.getParameter("paperId"));
        JSONObject res = new JSONObject();
        Record paperRecord = paperService.getRecordById(paperId);
        PaperVO papervo = paperRecord.into(PaperVO.class);
        GradeYearEntity gr = GradeYearService.getFromCaches(papervo.getGradeYear());
        papervo.setGradeYearName(gr==null?"":gr.getName());
        if(papervo.getPaperType()!=null){
            SysDictEntity paperTypeDict = SysDictService.getFromCaches("paper-type," + papervo.getPaperType());
            papervo.setPaperTypeTxt(paperTypeDict==null?"":paperTypeDict.getName());
        }
        Result<Record1<Object>> r = dsl.select(field("name")).from(table("major")).where(field("id").eq(papervo.getMajor())).fetch();
        if(r.size()==1){
            papervo.setMajorName(r.get(0).get(0,String.class));
        }
//        String title = papervo.getMajorName() + papervo.getGradeTxt();
        OutputStream os = null;
        res.put("code", 0);
        String name = DateTime.now().toString("yyMMddHHmmss");
        String tempFilePath = "d:/temp/"+name+".docx";
        String[] bigNums = new String[]{"一","二","三","四","五"};
        try {
            File temp = new File("d:/temp");
            if(!temp.exists()) {
                temp.mkdir();
            }
            res.put("path", tempFilePath);
            os = new FileOutputStream(tempFilePath);
            XWPFDocument document= new XWPFDocument();
            CTPageMar pgMar = document.getDocument().getBody().addNewSectPr().addNewPgMar();
            pgMar.setLeft(BigInteger.valueOf(1000)); // 设置左边距，单位为twip（1/20 of a point）
            pgMar.setRight(BigInteger.valueOf(1000)); // 设置右边距
            pgMar.setTop(BigInteger.valueOf(1440)); // 设置上边距
            pgMar.setBottom(BigInteger.valueOf(1440)); // 设置下边
            setTitle(document,papervo.getName(),20,"楷体_GB2312",true,ParagraphAlignment.CENTER);
            LibCategoryEntity cat = LibCategoryService.getFromCaches(papervo.getCategoryId());
            if(cat==null){
                msg = "//////////"+"请完善试卷信息";
                throw new RuntimeException(new Exception("考试科目不能为空"));
            }
            if(hasAnswer!=null){
                setTitle(document,"考试科目："+cat.getName()+"（"+papervo.getPaperTypeTxt()+"）参考答案",16,"楷体_GB2312",false,ParagraphAlignment.CENTER);
            }else{
                setTitle(document,"考试科目："+cat.getName()+"（"+papervo.getPaperTypeTxt()+"）",16,"楷体_GB2312",true,ParagraphAlignment.CENTER);
            }
            if(papervo.getGradeYear()==null){
                msg = "//////////"+"请完善试卷信息";
                throw new RuntimeException(new Exception("学年学期不能为空"));
            }
            GradeYearEntity grade = GradeYearService.getFromCaches(papervo.getGradeYear());
            if(papervo.getCollegeId()==null){
                msg = "//////////"+"请完善试卷信息";
                throw new RuntimeException(new Exception("学院/系不能为空"));
            }
            CollegeEntity coll = CollegeService.getFromCaches(papervo.getCollegeId());
            if(papervo.getTestType()==null){
                msg = "//////////"+"请完善试卷信息";
                throw new RuntimeException(new Exception("考试方式不能为空"));
            }
            SysDictEntity dict = SysDictService.getFromCaches("test-type," + papervo.getTestType());
            SysDictEntity dict3 = SysDictService.getFromCaches("semester," + papervo.getSemester());
            String str = StringUtils.rightPad("学年学期："+ grade.getName()+dict3.getName(),42," ");
            setTitle(document, str + "姓        名：",12,"楷体_GB2312",false,ParagraphAlignment.LEFT);
            str = StringUtils.rightPad("学院  / 系："+ coll.getName(),55," ");
            setTitle(document,str + "学        号：",12,"楷体_GB2312",false,ParagraphAlignment.LEFT);
            str = StringUtils.rightPad("考试方式："+ dict.getName(),64," ");
            setTitle(document,str + "年级专业：",12,"楷体_GB2312",false,ParagraphAlignment.LEFT);

            str = StringUtils.rightPad("考试时长："+ papervo.getHowlong() + "分钟",60 + (papervo.getHowlong()+"").length()/2," ");
            setTitle(document,str + "班        别：",12,"楷体_GB2312",false,ParagraphAlignment.LEFT);
            setTitle(document,"警示：《中山大学授予学士学位工作细则》第八条：“考试作弊者，不授予学士学位。”",12,"仿宋_GB2312",false,ParagraphAlignment.LEFT);
//            --------------------以下为试题区域，共三部分大题，总分100分--------------------
            XWPFParagraph tparagraph = document.createParagraph();
            tparagraph.setSpacingBetween(1.5,LineSpacingRule.AUTO);
            tparagraph.setSpacingAfterLines(0);
            tparagraph.setAlignment(ParagraphAlignment.CENTER);
            tparagraph.setVerticalAlignment(TextAlignment.TOP);
            setTitle2(tparagraph, "----", 12, "宋体", false, false);
            XWPFRun trun = tparagraph.createRun();
            CTShd shd = trun.getCTR().addNewRPr().addNewShd();
            shd.setFill("DCDCDC");
            setTitle3(trun,"以下为试题区域，共3道大题，总分100分,考生请在答题纸上作答主观题",12,"楷体_GB2312",false,false);
            XWPFRun trun2 = tparagraph.createRun();
            setTitle3(trun2,"----",12,"宋体",false,false);
            List<QuestionEntity> questions = questionService.select(QUESTION.PAPER_ID.eq(paperId),QUESTION.ORDERNO.asc());
            List<QuestionEntity>[] questionArr = new ArrayList[]{new ArrayList<QuestionEntity>(),new ArrayList<QuestionEntity>(),new ArrayList<QuestionEntity>(),new ArrayList<QuestionEntity>(),new ArrayList<QuestionEntity>()};
            for (QuestionEntity question : questions) {
                for(int i=0;i<5;i++){
                    if(question.getQuestionType()==(i+1)){
                        questionArr[i].add(question);
                    }
                }
            }
            int bigNum = 0,questionIndex = 0;
            for (int i=0;i<5;i++) {
                if(questionArr[i].size()!=0){
                    //设置题型
                    XWPFRun xwpfRun1 = getTextRun(document);
                    if(i>0){
                        xwpfRun1.addBreak();
                    }
                    dict = SysDictService.getFromCaches("question-type," + (i+1));
                    String questionTitle = bigNums[bigNum++] + "、"+dict.getName();
                    if(i==0&&papervo.getScore1()!=null){
                        BigDecimal score = new BigDecimal(papervo.getNum1()).multiply(papervo.getScore1());
                        questionTitle += "（共" + papervo.getNum1() + "小题，每小题" + (papervo.getScore1()+"").replace(".0","") + "分，共"  + (score + "").replace(".0","") + "分）";
                    }else if(i==1&&papervo.getScore2()!=null){
                        BigDecimal score = new BigDecimal(papervo.getNum2()).multiply(papervo.getScore2());
                        questionTitle += "（共" + papervo.getNum2() + "小题，每小题" + (papervo.getScore2()+"").replace(".0","") + "分，共"  + (score + "").replace(".0","") + "分）";
                    }else if(i==2&&papervo.getScore3()!=null){
                        BigDecimal score = new BigDecimal(papervo.getNum3()).multiply(papervo.getScore3());
                        questionTitle += "（共" + papervo.getNum3() + "小题，每小题" + (papervo.getScore3()+"").replace(".0","") + "分，共"  + (score + "").replace(".0","") + "分）";
                    }else if(i==3&&papervo.getScore4()!=null){
                        BigDecimal score = new BigDecimal(papervo.getNum4()).multiply(papervo.getScore4());
                        questionTitle += "（共" + papervo.getNum4() + "小题，每小题" + (papervo.getScore4()+"").replace(".0","") + "分，共"  + (score + "").replace(".0","") + "分）";
                    }else if(i==4&&papervo.getScore5()!=null){
                        BigDecimal score = new BigDecimal(papervo.getNum5()).multiply(papervo.getScore5());
                        questionTitle += "（共" + papervo.getNum5() + "小题，每小题" + (papervo.getScore5()+"").replace(".0","") + "分，共"  + (score + "").replace(".0","") + "分）";
                    }
                    xwpfRun1.setText(questionTitle);
                    boolean first = true;
                    for(QuestionEntity question : questionArr[i]){
                        questionIndex++;
                        if(question.getText().endsWith("<br/>")){
                            int lastIndex = question.getText().lastIndexOf("<br/>");
                            question.setText(StringUtils.substring(question.getText(),0,lastIndex));
                        }
                        question.setText(StringUtils.trim(question.getText()));
                        XWPFParagraph paragraph = getParagraph(document);
                        if(!first){
                            paragraph.createRun().addBreak();
                        }
                        first = false;
                        setQuestion(question,questionIndex,document,paragraph,null);//设置题干
                        if(question.getQuestionType().intValue()==5){
                            if(hasAnswer!=null){
                                paragraph = getParagraph(document);
                                setAnswerText(question.getAnswerText(),document,paragraph);
                            }
                        }
                        List<ChoiceEntity> choices = choiceService.select(CHOICE.QUESTION_ID.eq(Long.valueOf(question.getId())), CHOICE.INDEX_LETTER.asc());
                        String rightAnswer = "";
                        for (ChoiceEntity choice : choices) {
                            setChoice(choice,document,null);
                            if(hasAnswer!=null){
                                if(question.getQuestionType().intValue()==5){
                                    paragraph = getParagraph(document);
                                    setAnswerText(choice.getAnswerText(),document,paragraph);
                                }else{
                                    if(choice!=null&&choice.getRight()==null){
                                        msg = "//////////"+StringUtils.substring(question.getText(),0,50)+"：请指定正确答案";
                                        throw new RuntimeException(new Exception("运行时错误"));
                                    }
                                    if(choice!=null&&choice.getRight()==1){
                                        rightAnswer = choice.getIndexLetter();
                                    }
                                }

                            }
                        }
                        if(hasAnswer!=null&&question.getQuestionType().intValue()!=5){
                            setAnalysis("解题思路：",question.getAnalysis(),document);
                            if(question.getQuestionType().intValue()!=4){
                                XWPFRun xwpfRun2 = getTextRun(document);
                                xwpfRun2.setText("正确答案：" + rightAnswer);
                            }else{
                                
//                                String axt = dsl.select(QUESTION.ANSWER_TEXT).from(QUESTION).where(QUESTION.ID.eq(Long.valueOf(question.getId()))).fetchOneInto(String.class);
                                setAnalysis("答案说明：",question.getAnswerText(),document);
//                                setAnswerText(axt,document);
                                
                            }
                        }
                    }
                }
            }
            document.write(os);
            download(tempFilePath,name + ".docx", request, response);
        } catch (Exception e1) {
            res.put("code", 1);
            res.put("msg", "导出失败，请重试" + msg);
            e1.printStackTrace();
        }finally {
            if(os!=null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                FileUtils.forceDelete(new File(tempFilePath));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return res;
    }
    private void setQuestion(QuestionEntity question,int questionIndex,XWPFDocument document,XWPFParagraph paragraph,XWPFRun xwpfRun) throws IOException, InvalidFormatException {
        String text = question.getText();
        if(text.indexOf("&")!=-1){
            Set<String> symbolKeys = Constant.symbolMap.keySet();
            for (String symbolKey : symbolKeys) {
                text = StringUtils.replace(text,symbolKey,Constant.symbolMap.get(symbolKey));
            }
        }
//        XWPFParagraph paragraph = getParagraph(document);
        setQuestionText(questionIndex + ". " + text,document,paragraph,xwpfRun);
    }
    private void setQuestionText(String text,XWPFDocument document,XWPFParagraph paragraph,XWPFRun xwpfRun) throws IOException, InvalidFormatException {

        text = text.replace("&quot;","'");
        text = text.replace("<br />","<br>").replace("<br/>","<br>");
        int index1 = text.indexOf("<img ");
        int index2 = text.indexOf("<table ");
        int index3 = text.indexOf("<sup>");
        int index4 = text.indexOf("<sub>");
        int index5 = text.indexOf("<span ");
        if(index5==-1){
            index5 = text.indexOf("<span>");
        }
        int index6 = text.indexOf("<br>");
        int index7 = text.indexOf("<em>");
        int index8 = text.indexOf("<b>");
        int index9 = text.indexOf("<strong>");
        if(xwpfRun==null){
            xwpfRun = getTextRun(paragraph);
        }
        if (index1==-1&&index2==-1&&index3==-1&&index4==-1&&index5==-1&&index6==-1&&index7==-1&&index8==-1&&index9==-1){
            xwpfRun.setText(text);
        }else{
            int minIndex = 1000000000;
            if(index1!=-1){
                minIndex = index1;
            }
            if(index2!=-1&&minIndex>index2){
                minIndex = index2;
            }
            if(index3!=-1&&minIndex>index3){
                minIndex = index3;
            }
            if(index4!=-1&&minIndex>index4){
                minIndex = index4;
            }
            if(index5!=-1&&minIndex>index5){
                minIndex = index5;
            }
            if(index6!=-1&&minIndex>index6){
                minIndex = index6;
            }
            if(index7!=-1&&minIndex>index7){
                minIndex = index7;
            }
            if(index7!=-1&&minIndex>index7){
                minIndex = index7;
            }
            if(index8!=-1&&minIndex>index8){
                minIndex = index8;
            }
            if(index9!=-1&&minIndex>index9){
                minIndex = index9;
            }
            if(minIndex>0){
                String txt1 = StringUtils.substring(text,0,minIndex);
                xwpfRun.setText(txt1);
                String txt2 = StringUtils.substring(text,minIndex);
                if(!txt2.equals("<br>")){
                    setQuestionText(txt2,document,paragraph,xwpfRun);
                }
                return;
            }
            if(minIndex==index1){//图片
                resolvePicture(text, document, paragraph, minIndex);
            }else if(minIndex==index2){//table
                resolveTable(text, document, paragraph);
            }else if(minIndex==index3){//sup
                resolveSup(text, document, paragraph,"sup");
            }else if(minIndex==index4){//sub
                resolveSub(text, document, paragraph,"sub");
            }else if(minIndex==index5){//span
                resolveSpan(text, document, paragraph,"span");
            }else if(minIndex==index6){//<br>
                xwpfRun.addBreak();
                String txt = StringUtils.substring(text,4);
                setQuestionText(txt,document,paragraph,xwpfRun);
            }else if(minIndex==index7){//<em>
                resolveEm(text, document, paragraph,"em");
            }else if(minIndex==index8){//<b>
                resolveB(text, document, paragraph,"b");
            }else if(minIndex==index9){//<b>
                resolveStrong(text, document, paragraph,"strong");
            }
        }
    }
    private void setChoice(ChoiceEntity choice,XWPFDocument document,XWPFParagraph paragraph) throws IOException, InvalidFormatException {
        paragraph = getParagraph(document);
        XWPFRun xwpfRun = getTextRun(paragraph);
        String text = choice.getText();
        xwpfRun.setText(choice.getIndexLetter()+". ");
        text = text.replace("<br />","<br>").replace("<br/>","<br>");
        text = text.replace("<br>","");
        if(text.indexOf("&")!=-1){
            Set<String> symbolKeys = Constant.symbolMap.keySet();
            for (String symbolKey : symbolKeys) {
                text = StringUtils.replace(text,symbolKey,Constant.symbolMap.get(symbolKey));
            }
        }
        if(text.endsWith("<br/>")){
            text = text.substring(0,text.lastIndexOf("<br/>"));
        }
        setQuestionText(text,document,paragraph,xwpfRun);
    }
    private void setAnalysis(String title,String analysis,XWPFDocument document) throws IOException, InvalidFormatException {
        XWPFParagraph paragraph = getParagraph(document);
        XWPFRun xwpfRun = getTextRun(paragraph);
        xwpfRun.setText(title);
        if(analysis!=null&&analysis.endsWith("<br/>")){
            analysis = analysis.substring(0,analysis.lastIndexOf("<br/>"));
        }
        if(analysis==null||analysis.isEmpty()){
            xwpfRun.setText("暂无。");
        }else{
            if(analysis.indexOf("&")!=-1){
                Set<String> symbolKeys = Constant.symbolMap.keySet();
                for (String symbolKey : symbolKeys) {
                    analysis = StringUtils.replace(analysis,symbolKey,Constant.symbolMap.get(symbolKey));
                }
            }
            setQuestionText(analysis,document,paragraph,xwpfRun);
//            setAnalysisText(analysis,document,paragraph,xwpfRun);
        }
    }
    private void setAnswerText(String answerTxt,XWPFDocument document,XWPFParagraph paragraph) throws IOException, InvalidFormatException {
//        XWPFParagraph paragraph = getParagraph(document);
        XWPFRun xwpfRun = getTextRun(paragraph);
        xwpfRun.setText("答案说明：");
        if(answerTxt==null||answerTxt.isEmpty()){
            xwpfRun.setText("暂无。");
        }else{
            if(answerTxt.indexOf("&")!=-1){
                Set<String> symbolKeys = Constant.symbolMap.keySet();
                for (String symbolKey : symbolKeys) {
                    answerTxt = StringUtils.replace(answerTxt,symbolKey,Constant.symbolMap.get(symbolKey));
                }
            }
            setQuestionText(answerTxt,document,paragraph,xwpfRun);
//            setAnalysisText(answerTxt,document,paragraph,xwpfRun);
        }
    }

    private void resolveSup(String text, XWPFDocument document, XWPFParagraph paragraph,String name) throws InvalidFormatException, IOException {
        int endIndex = text.indexOf("</"+name+">") + 6;
        String supTxt = StringUtils.substring(text,0, endIndex);
        Document dom = null;
        try {
            dom = DocumentHelper.parseText(supTxt);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        Element node = (Element)dom.selectSingleNode(name);
        XWPFRun xwpfRun = getTextRun(paragraph);
        xwpfRun.setSubscript(VerticalAlign.SUPERSCRIPT);
        xwpfRun.setText(node.getText());
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            xwpfRun = getTextRun(paragraph);
            setQuestionText(text, document, paragraph,xwpfRun);
        }
    }
    private void resolveSub(String text, XWPFDocument document, XWPFParagraph paragraph,String name) throws InvalidFormatException, IOException {
        int endIndex = text.indexOf("</"+name+">") + 6;
        String supTxt = StringUtils.substring(text,0, endIndex);
        Document dom = null;
        try {
            dom = DocumentHelper.parseText(supTxt);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        Element node = (Element)dom.selectSingleNode(name);
        XWPFRun xwpfRun = getTextRun(paragraph);
        xwpfRun.setSubscript(VerticalAlign.SUBSCRIPT);
        xwpfRun.setText(node.getText());
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            xwpfRun = getTextRun(paragraph);
            setQuestionText(text, document, paragraph,xwpfRun);
        }
    }
    private void resolveEm(String text, XWPFDocument document, XWPFParagraph paragraph,String name) throws InvalidFormatException, IOException {
        int endIndex = text.indexOf("</"+name+">") + 5;
        String supTxt = StringUtils.substring(text,0, endIndex);
        Document dom = null;
        try {
            dom = DocumentHelper.parseText(supTxt);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        Element node = (Element)dom.selectSingleNode(name);
        XWPFRun xwpfRun = getTextRun(paragraph);
        xwpfRun.setItalic(true);
        setStyle(node, xwpfRun);
        xwpfRun.setText(node.getText());
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            xwpfRun = getTextRun(paragraph);
            setQuestionText(text, document, paragraph,xwpfRun);
        }
    }
    private void resolveB(String text, XWPFDocument document, XWPFParagraph paragraph,String name) throws InvalidFormatException, IOException {
        int endIndex = text.indexOf("</"+name+">") + 4;
        String supTxt = StringUtils.substring(text,0, endIndex);
        Document dom = null;
        try {
            dom = DocumentHelper.parseText(supTxt);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        Element node = (Element)dom.selectSingleNode(name);
        XWPFRun xwpfRun = getTextRun(paragraph);
        xwpfRun.setBold(true);
        setStyle(node, xwpfRun);
        xwpfRun.setText(node.getText());
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            xwpfRun = getTextRun(paragraph);
            setQuestionText(text, document, paragraph,xwpfRun);
        }
    }
    private void resolveStrong(String text, XWPFDocument document, XWPFParagraph paragraph,String name) throws InvalidFormatException, IOException {
        int endIndex = text.indexOf("</"+name+">") + 9;
        String supTxt = StringUtils.substring(text,0, endIndex);
        Document dom = null;
        try {
            dom = DocumentHelper.parseText(supTxt);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        Element node = (Element)dom.selectSingleNode(name);
        XWPFRun xwpfRun = getTextRun(paragraph);
        xwpfRun.setBold(true);
        setStyle(node, xwpfRun);
        xwpfRun.setText(node.getText());
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            xwpfRun = getTextRun(paragraph);
            setQuestionText(text, document, paragraph,xwpfRun);
        }
    }
    private void resolveSpan(String text, XWPFDocument document, XWPFParagraph paragraph,String name) throws InvalidFormatException, IOException {
        int endIndex = text.indexOf("</"+name+">") + 7;
        String supTxt = StringUtils.substring(text,0, endIndex);
        if(supTxt.indexOf("&nbsp;<img")!=-1){
            supTxt = supTxt.replace("&nbsp;<img","<img");
        }
        Document dom = null;
        try {
            dom = DocumentHelper.parseText(supTxt);
        } catch (DocumentException e) {
            if(supTxt.indexOf("<span>")!=-1){
                supTxt = supTxt.replace("<span>","<span><![CDATA[")
                        .replace("</span>","]]></span>");
            }else
            if(supTxt.indexOf("<span ")!=-1){
                int gtIndex = supTxt.indexOf(">");
                String str = supTxt.substring(0,gtIndex + 1);
                supTxt = supTxt.replace(str,str + "<![CDATA[").replace("</span>","]]></span>");
            }
            try {
                dom = DocumentHelper.parseText(supTxt);
            } catch (DocumentException e2) {

                if(supTxt.length()>100){
                    msg = e.getMessage() + "/提醒：" + supTxt.substring(0,100);
                }else{
                    msg = e.getMessage() + "/提醒：" + supTxt;
                }

                throw new RuntimeException(e2);
            }
        }
        Element root = dom.getRootElement();
        XWPFRun xwpfRun = getTextRun(paragraph);
        List<Element> elements = root.elements();
        if(elements.size()>0){
            for (Element element : elements) {
                if(element.getName().equals("img")){
                    resolvePicture(element.getText(), document, paragraph, 1);
                }
                if(element.getName().equals("sup")){
                    xwpfRun.setSubscript(VerticalAlign.SUPERSCRIPT);
                    xwpfRun.setText(element.getText());
                }
                if(element.getName().equals("sub")){
                    xwpfRun.setSubscript(VerticalAlign.SUBSCRIPT);
                    xwpfRun.setText(element.getText());
                }
            }
        }else {

            Element node = (Element)dom.selectSingleNode(name);
            setStyle(node, xwpfRun);
            String txt = node.getText().trim();
            if(txt.equals("\uD835\uDF36")){
                txt = "α";
            }
            if("π".equals(txt)){
                xwpfRun = getTextRun2(paragraph);
            }
            xwpfRun.setText(txt);
        }
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            xwpfRun = getTextRun(paragraph);
            setQuestionText(text, document, paragraph,xwpfRun);
        }

    }

    private void setStyle(Element node, XWPFRun xwpfRun) {
        Attribute styleNode = node.attribute("style");
        if(styleNode!=null){
            String style = styleNode.getText();
            if(style.contains("bolder")){
                xwpfRun.setBold(true);
            }
            if(style.contains("italic")){
                xwpfRun.setItalic(true);
            }
            if(style.contains("line-through")){
                xwpfRun.setStrikeThrough(true);
            }
        }
    }

    private void resolveTable(String text, XWPFDocument document, XWPFParagraph paragraph) throws InvalidFormatException, IOException {
        XWPFRun xwpfRun = getTextRun(paragraph);
        int endIndex = text.indexOf("</table>") + 8;
        String tableTxt = StringUtils.substring(text,0, endIndex);
        if(tableTxt.indexOf("<table ")>0){
            String txt1 = StringUtils.substringBefore(tableTxt,"<table ");
            xwpfRun.setText(txt1);
        }

        WordUtil.handleTableHtml(document,tableTxt);
        paragraph = document.createParagraph();
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            xwpfRun = getTextRun(paragraph);
            setQuestionText(text, document, paragraph,xwpfRun);
        }
    }
    private void resolvePicture(String text, XWPFDocument document, XWPFParagraph paragraph, int index) throws InvalidFormatException, IOException {
        int endIndex = text.indexOf("'/>");
        if(endIndex!=-1){
            endIndex += 3;
        }else{
            endIndex = text.indexOf("\"/>");
            if(endIndex!=-1){
                endIndex += 3;
            }else{
                endIndex = text.indexOf(" />") + 3;
            }

        }
        String imgTxt = StringUtils.substring(text,0, endIndex);
        XWPFRun xwpfRun = paragraph.createRun();
        try {
            addPicture(imgTxt, document, xwpfRun);
        } catch (TranscoderException e) {
            throw new RuntimeException(e);
        }
        text = StringUtils.substring(text, endIndex);
        if (text.length()>0){
            setQuestionText(text, document, paragraph,xwpfRun);
        }
    }
    private void addPicture(String text,XWPFDocument document,XWPFRun xwpfRun) throws InvalidFormatException, IOException, TranscoderException {
        Document dom = null;
        try {
            dom = DocumentHelper.parseText(text);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        Element node = (Element)dom.selectSingleNode("img");
        String imgsrc = node.attributeValue("src");
        String dir = "d:/eqfile/";
        String src = dir + imgsrc;
        BufferedImage bufferImg = null;
        String base64 = null;
        if(imgsrc.startsWith("https://")){
            String svgData = HttpUtil.get(imgsrc, 30000);
            bufferImg = svg2BufferedImage(svgData);
//            bufferImg = handleImage(bufferImg);
            base64 = image2base64(bufferImg);
        }
        int[] sizeArray = new int[2];
        try {
            if(imgsrc.startsWith("data:image")){
                byte[] bytes = new BASE64Decoder().decodeBuffer(imgsrc);
                String picId = document.addPictureData(bytes, XWPFDocument.PICTURE_TYPE_PNG);
                WordUtils.addPictureToRun(xwpfRun,picId,XWPFDocument.PICTURE_TYPE_PNG,sizeArray[0],sizeArray[1]);
            }else {
                if(base64==null){
                    File imageFile = new File(src);
                    if(imageFile.exists()){
                        if(imageFile.exists()){
                            bufferImg = ImageIO.read(imageFile);
                            byte[] fileContent = new byte[(int) imageFile.length()];
                            try (FileInputStream fileInputStream = new FileInputStream(imageFile)) {
                                fileInputStream.read(fileContent);
                            }
                            base64 = Base64.getEncoder().encodeToString(fileContent);
                        }
                    }
                }
                if(base64!=null){
                    int width = 100;
                    int height = 100;
                    if(bufferImg!=null){
                        width = bufferImg.getWidth();
                        height = bufferImg.getHeight();

                    }
                    int po = 15000;
                    int uwidth = Units.toEMU(width),uheight = Units.toEMU(height);
                    if(15895800<=uwidth){
                        uwidth = uwidth/4;
                        uheight = uheight/4;
                    }
                    int widthEMU = uwidth/po;
                    int heightEMU = uheight/po;
                    if(widthEMU>1300){
                        widthEMU/=2;
                        heightEMU = heightEMU/2;
                        if(widthEMU>1300){
                            widthEMU/=2;
                            heightEMU = heightEMU/2;
                        }
                    }
                    if(widthEMU>400){
                        widthEMU/=2;
                        heightEMU/=2;
                    }
                    sizeArray[0] = widthEMU;
                    sizeArray[1] = heightEMU;
                    byte[] bytes = new BASE64Decoder().decodeBuffer(base64);
                    String picId = document.addPictureData(bytes, XWPFDocument.PICTURE_TYPE_PNG);
                    WordUtils.addPictureToRun(xwpfRun,picId,XWPFDocument.PICTURE_TYPE_PNG,sizeArray[0],sizeArray[1]);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }


    }
    private static BufferedImage svg2BufferedImage(String svgData) throws TranscoderException, IOException {
        PNGTranscoder transcoder = new PNGTranscoder();
        TranscoderInput input = new TranscoderInput(new StringReader(svgData));
        ByteArrayOutputStream pngOutputStream =  new ByteArrayOutputStream();
        TranscoderOutput output = new TranscoderOutput(pngOutputStream);
        transcoder.transcode(input,output);
        pngOutputStream.flush();
        ByteArrayInputStream pngInputStream = new ByteArrayInputStream(pngOutputStream.toByteArray());
        BufferedImage image = ImageIO.read(pngInputStream);
        pngInputStream.close();
        pngOutputStream.close();
        return image;
    }
    private static String image2base64(BufferedImage image) throws IOException {
//        BufferedImage backgroundImage = new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_RGB);
//        Graphics2D g = backgroundImage.createGraphics();
//        g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
//        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//        g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
//        g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
//        g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
//        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
//        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
//        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
//        g.setColor(Color.WHITE);
//        g.fillRect(0,0,backgroundImage.getWidth(),backgroundImage.getHeight());
//        g.drawImage(image,0,0,null);
//        g.dispose();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image,"png",baos);
        baos.flush();
        byte[] imageBytes = baos.toByteArray();
        baos.close();
        return Base64.getEncoder().encodeToString(imageBytes);
    }

    private static HostnameVerifier hostnameVerifier() {
        return (s, sslSession) -> true;
    }
    private static SSLSocketFactory sslSocketFactory() {
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        TrustManager[] tm = new TrustManager[]{trustManager};
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, tm, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private CTPPr getProps(XWPFParagraph paragraph) {
        CTPPr properties = paragraph.getCTP().addNewPPr();
        CTSpacing spacing = properties.addNewSpacing();
        spacing.setAfter(BigInteger.valueOf(0));
        return properties;
    }

    private XWPFParagraph getParagraph(XWPFDocument document){
        XWPFParagraph paragraph = document.createParagraph();
        paragraph.setSpacingAfterLines(100);
        paragraph.setAlignment(ParagraphAlignment.LEFT);
        paragraph.setVerticalAlignment(TextAlignment.TOP);
        CTPPr props = getProps(paragraph);
        paragraph.getCTP().setPPr(props);
        paragraph.setSpacingBetween(1.5,LineSpacingRule.AUTO);
        return paragraph;
    }
    private XWPFRun getTextRun(XWPFDocument document){
        XWPFParagraph paragraph = document.createParagraph();
        paragraph.setSpacingAfterLines(100);
        paragraph.setAlignment(ParagraphAlignment.LEFT);
        paragraph.setVerticalAlignment(TextAlignment.TOP);
        CTPPr props = getProps(paragraph);
        paragraph.getCTP().setPPr(props);
        paragraph.setSpacingBetween(1.5,LineSpacingRule.AUTO);
        XWPFRun xwpfRun = getTextRun(paragraph);
        return xwpfRun;
    }
    private XWPFRun getTextRun(XWPFParagraph paragraph){
        XWPFRun xwpfRun = paragraph.createRun();
        xwpfRun.setFontSize(12);
        xwpfRun.setFontFamily("宋体");
        xwpfRun.setFontFamily("Times New Roman");
        return xwpfRun;
    }
    private XWPFRun getTextRun2(XWPFParagraph paragraph){
        XWPFRun xwpfRun = paragraph.createRun();
        xwpfRun.setFontSize(12);
        xwpfRun.setFontFamily("Times New Roman");
        return xwpfRun;
    }
    @RequestMapping("/download")
    public void download(String filePath,String fileName,HttpServletRequest request,HttpServletResponse res) throws IOException {
        File file = new File(filePath);
        if(file.exists()){
            res.setHeader("Content-Disposition", "attachment; filename="+new String(fileName.getBytes("GB2312"),"iso-8859-1"));
            ServletOutputStream os = res.getOutputStream();
            os.write(FileUtils.readFileToByteArray(file));
            os.flush();
            os.close();
        }else{
            res.setContentType("text/html");
            res.setCharacterEncoding("utf-8");
            PrintWriter out = res.getWriter();
            out.write("<script>parent.layer.tips('该附件不存在')</script>");
            out.flush();

        }
    }
}
